package symbol;

import java.util.HashMap;
import java.util.Set;
import java.util.Vector;
import error.Error;
import syntaxtree.*;

public class Class {

	private HashMap<Symbol, Type> variables;
	private Vector<Method> methods;
	private Vector<Symbol> methodsSymbols;
	private Symbol extender;
	private Symbol name;
	private Type type;

	public String toString() {
		String r = new String();
		String pre = "    ";
		r = "Class "+ name;
		if(extender != null) 
			r += " extends "+ extender.toString();
		r+= " {\n";

		Set<Symbol> hs = variables.keySet();
		for(Symbol key : hs)
			r += pre + variables.get(key).getClass().getSimpleName() +" "+ key +";\n";

		for(int i=0; i<methods.size(); i++)
			r += methods.get(i).toString(pre);
		r += "}\n";         
		return r;
	}

	public Class(Symbol name) {
		this.name = name;
		type = new IdentifierType(name.toString());
		variables = new HashMap<Symbol, Type>();
		methods = new Vector<Method>();
		methodsSymbols = new Vector<Symbol>();
		extender = null;
	}

	public Class(Symbol name, Symbol ext) {
		this.name = name;
		type = new IdentifierType(name.toString());
		variables = new HashMap<Symbol, Type>();
		methods = new Vector<Method>();
		methodsSymbols = new Vector<Symbol>();
		extender = ext;
		if (name.equals(ext)) {
			extender = null;
			Error.getInstance().addErro("Classe: "+
					name.toString()+" esta estendendo ela mesma");
		}// end if
	}

	public boolean compare(Class s) {
		return this.name.equals(s.name);
	}

	public Method addMethod(Symbol m, Vector<Formal> listIn, Type returnType) {
		Method mt = new Method(m, listIn, returnType);
		methods.add(mt);
		methodsSymbols.add(m);
		return mt;
	}

	public void addVariable(Symbol variable, Type type2) {
		variables.put(variable, type2);
	}

	public Vector<Method> getMethodVector(Symbol meth) {
		Vector<Method> meths = new Vector<Method>();
		for (int i = 0; i < methodsSymbols.size(); i++) {
			if (meth.equals(methodsSymbols.elementAt(i)))
				meths.add(methods.elementAt(i));
		}
		return meths;
	}

	public Method getMethodMain(Symbol meth) {
		for (int i = 0; i < methodsSymbols.size(); i++) {
			if (meth.equals(methodsSymbols.elementAt(i)))
				return methods.elementAt(i);
		}
		return null;
	}

	public Symbol getName() {
		return name;
	}

	public HashMap<Symbol, Type> getVariables() {
		return variables;
	}

	public Vector<Method> getMethods() {
		return methods;
	}

	public Symbol getExtender() {
		return extender;
	}

	public Type getType() {
		return type;
	}

	public int getNumberOfVariables() {
		return variables.size();
	}

	public Method getMethod(String s){
		for (Method m : methods)
			if (m.toString().equals(s))
				return m;
		return null;
	}

	public boolean containsMethod(String s){
		for (Method m : methods)
			if (m.toString().equals(s))
				return true;
		return false;
	}

	public String getClassName() {
		return name.toString();
	}

	public boolean containsVar(String s) {
		for(Symbol v : variables.keySet())
			if (v.toString().equals(s))
				return true;
		return false;
	}

	public Type getFieldType(String s) {
		for(Symbol v : variables.keySet())
			if (v.toString().equals(s))
				return variables.get(v);
		return null;
	}

}